Drill Down

From Documentation



Here we talk about 2 ways to achieve a drill-down function. One is simply using ZK Charts built-in feature, and another is implemented manually.

Built-in Drilldown

The simplest way to implement drilldown is to use the built-in feature. ZK Charts demo has a good example please refer to http://www.zkoss.org/zkchartsdemo/column_drilldown

But under this way, it only can display one series after you drill down a series. If you need to display multiple series, you need to adopt the approach mentioned below.

Drilldown on Demand

In cases where the drill down data is expensive to calculate, you can add drill down series on demand by listening to ChartsEvents.ON_PLOT_DRILL_DOWN / ChartsEvents.ON_PLOT_DRILL_UP and calling chart.addSeriesAsDrilldown.

org.zkoss.zkcharts.essentials.DrilldownOnDemandComposer

        chart.addEventListener(ChartsEvents.ON_PLOT_DRILL_DOWN, (ChartsEvent e) -> {
            Point parent = e.getPoint();
            Point[] childPoints = loadPoints(parent); //e.g. from DB
            Series series = new Series(parent.getDrilldown(), childPoints);
            series.setName("Details of " + parent.getName());
            chart.addSeriesAsDrilldown(parent, series);
        });
        chart.addEventListener(ChartsEvents.ON_PLOT_DRILL_UP, e -> { ... });

To enable the listeners you need to call point.setDrilldown() for each point (having drill down data) in your initial and in dynamically added drill down series.

A fully runnable example - featuring infinite drill down - is available in our zkchartsessentials demo project:

NOTE: Until version 3.0.3, this feature requires 2 simple workarounds mentioned in ZKCHARTS-80 and ZKCHARTS-81

Drill Down Manually

The main benefit to implement drill-down by yourselves is flexibility, and this way can show multiple series after drilling down a series. But you have to take care all things during drill-down like UI update and data loading.

Remember Drill-down Level

You might have multiple levels of data to drill down, and the controller needs to know which level the chart's data is to decide loading corresponding data. We can store the drill-down level as an attribute of Charts component.

package org.zkoss.zkcharts.essentials;

import org.zkoss.chart.Charts;
import org.zkoss.chart.ChartsEvent;
import org.zkoss.chart.model.DefaultCategoryModel;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Button;

/**
 * An example to demonstrate drill-down manually by listening "onPlotClick"<br/>
 * Listening "onPlotDrillDown" is a possible solution, but it will throw an exception when there are multiple series.
 * @author hawk
 *
 */
public class DisplayMultipleSeriesComposer extends SelectorComposer<Component> {

    @Wire
    private Charts chart;
    @Wire("#back")
    private Button backButton;
    
    private DefaultCategoryModel model = new DefaultCategoryModel();
    private String DRILLDOWN_LEVEL = "LEVEL"; 
    
    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        chart.getYAxis().setTitle("Values");
        initModel();
        chart.setAttribute(DRILLDOWN_LEVEL, new Integer(0)); 
        updateDrilldownStatus();
    }
...
}
  • Line 33: We store drill-down level as an attribute of the Charts. You can store any information to indicate the drill-down status.

Load Drill-down Data

Now we can implement the drill-down behavior by listening onPlotClick event and replace model's data upon which market of a series you click.

org.zkoss.zkcharts.essentials.DisplayMultipleSeriesComposer.java

    /**
     * Switch the chart's model with corresponding data.  
     */
    @Listen("onPlotClick = #chart")
    public void drilldown(ChartsEvent e){
    	Integer level = (Integer)chart.getAttribute(DRILLDOWN_LEVEL);
    	if (level == 0){
	    	model.clear();
	    	if (MARKET1.equals(e.getCategory())){
	    		loadDrilldownModel1();
	    	}else{
	    		loadDrilldownModel2();
	    	}
	    	level++;
	    	chart.setAttribute(DRILLDOWN_LEVEL, level);
	    	updateDrilldownStatus();
    	}
    }

Drill-up Button

Since we don't use the built-in drill-down feature, we need to create our own drill-up button.

displayMultipleSeries.zul

<zk>
	<window apply="org.zkoss.zkcharts.essentials.DisplayMultipleSeriesComposer" >
	    <charts id="chart" type="column" title="Market Share" 
	        subtitle="Click the columns to view regions" width="600"/>
	    <button id="back" label="back to All Market" visible="false" 
	    style="position: absolute; z-index:100; left:460px; top:40px"/>
	</window>
</zk>
  • Line 4: The drill-up button is only visible after drilling down a series.
  • Line 5: We move the button to the up-right corner to make it similar with built-in drill-up button.


When users click the drill-up button, we reload back to original data and change the button's visibility and cursor's style..

An event listener for drill-up button in DisplayMultipleSeriesComposer.java

    @Listen("onClick = #back")
    public void reloadMarket(){
    	Integer level = (Integer)chart.getAttribute(DRILLDOWN_LEVEL);
    	if (level == 1){
    		model.clear();
    		initModel();
    		level--;
    		chart.setAttribute(DRILLDOWN_LEVEL, level);
    		updateDrilldownStatus();
    	}
    }

    private void updateDrilldownStatus(){
    	Integer level = (Integer)chart.getAttribute(DRILLDOWN_LEVEL);
    	if (level == 0){
    		chart.getPlotOptions().getSeries().setCursor("pointer");
    		backButton.setVisible(false);
    	}else{
    		chart.getPlotOptions().getSeries().setCursor("normal");
    		backButton.setVisible(true);
    	}
    }



< Get Complete Source Code of This Book >


Last Update : 2022/01/18

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.